/*
MIT License

Copyright (c) 2019 МГТУ им. Н.Э. Баумана, кафедра ИУ-6, Михаил Фетисов,

https://bmstu.codes/lsx/simodo/loom
*/

#include "simodo/variable/convert/Ast.h"
#include "simodo/inout/convert/functions.h"

#include <algorithm>

namespace simodo::variable
{

    Value toValue(const ast::Tree & tree)
    {
        return std::make_shared<Object>(VariableSet_t {{
            {u"files",  toValue(tree.files())},
            {u"root",   toValue(tree.root())},
        }});
    }

    Value toValue(const inout::uri_set_t & files)
    {
        std::vector<Value> file_set;

        for(const std::string & s : files)
            file_set.push_back(inout::toU16(s));

        return std::make_shared<Array>( file_set );
    }

    Value toValue(const ast::Node & node)
    {
        return std::make_shared<Object>(VariableSet_t {{
            {u"host",       node.host()},
            {u"operation",  node.operation()},
            {u"token",      toValue(node.token())},
            {u"bound",      toValue(node.bound())},
            {u"branches",   toValue(node.branches())},
        }});
    }

    Value toValue(const inout::Token & token)
    {
        return std::make_shared<Object>(VariableSet_t {{
            {u"type",           static_cast<int64_t>(token.type())},
            {u"lexeme",         token.lexeme()},
            {u"token",          token.token()},
            {u"qualification",  static_cast<int64_t>(token.qualification())},
            {u"context",   static_cast<int64_t>(token.context())},
            {u"location",       toValue(token.location())},
        }});
    }

    Value toValue(const inout::TokenLocation & location)
    {
        return std::make_shared<Object>(VariableSet_t {{
            {u"uri_index",  location.uri_index()},
            {u"range",      toValue(location.range())},
        }});
    }

    Value toValue(const inout::Range & range)
    {
        return std::make_shared<Object>(VariableSet_t {{
            {u"start",  toValue(range.start())},
            {u"end",    toValue(range.end())},
        }});
    }
    
    Value toValue(const inout::Position & position)
    {
        return std::make_shared<Object>(VariableSet_t {{
            {u"line",       static_cast<int64_t>(position.line())},
            {u"character",  static_cast<int64_t>(position.character())},
        }});
    }

    Value toValue(const std::vector<ast::Node> & branches)
    {
        std::vector<Value> branch_values;

        for(const ast::Node & node : branches)
            branch_values.push_back(toValue(node));

        return std::make_shared<Array>( branch_values );
    }

}